import * as THREE from '../jsm/three.module.js';

import { requestLand } from '../../../../api/server';

import { worker } from './worker.js';

let TOOLACTION = false; // 工具执行中？

let landGroup; // 地质组
let landMaterial; // 地质材质

let initReuquestLand = false; // 初始化土地？
let loadLandSucceed = false; // 加载地质完成

let currArea;

let landGeometry; // 泥层对象的几何体

// let shipbox = new THREE.Mesh(new THREE.BoxGeometry(8, 8, 8), new THREE.MeshBasicMaterial({ color: 0x00ff00 }));

// 地质材质
function landMaterialFunc() {

    // return new THREE.MeshPhongMaterial({ color: 0x666666, side: 0 });

    if (landMaterial) return landMaterial;

    const HeightColor = ['#define PHONG', 'varying vec3 HeightColor;'].join('\n');

    const color0 = 'vec3(0.7176, 0.6588, 0.5686)', // 基础泥色
        color1 = 'vec3(0.6549, 0.5294, 0.3765)', // 青灰段泥色
        color2 = 'vec3(0.4157, 0.3137, 0.2549)', // 黑椒顿泥
        color3 = 'vec3(0.4863, 0.2471, 0.1765)', // 大红袍泥
        color4 = 'vec3(0.2824, 0.1647, 0.1255)', // 底槽清泥
        color5 = 'vec3(0.2196, 0.1725, 0.1882)'; // 紫泥

    const judgmentClamp =
        `
    if (position.y > -12.) {
        HeightColor = ${color0};
    } else if (position.y > -13.) {
        HeightColor = mix(${color1}, ${color0}, clamp(position.y + 13., 0., 1.));
    } else if (position.y > -14.) {
        HeightColor = mix(${color2}, ${color1}, clamp(position.y + 14., 0., 1.));
    } else if (position.y > -15.) {
        HeightColor = mix(${color3}, ${color2}, clamp(position.y + 15., 0., 1.));
    } else if (position.y > -16.) {
        HeightColor = mix(${color4}, ${color3}, clamp(position.y + 16., 0., 1.));
    } else {
        HeightColor = mix(${color5}, ${color4}, clamp(position.y + 17., 0., 1.));
    }`;

    landMaterial = new THREE.MeshPhongMaterial({ color: 0x666666, side: 0 });

    landMaterial.onBeforeCompile = function (shader) {

        // console.log(shader.uniforms);
        // console.log(shader.vertexShader);
        // console.log(shader.fragmentShader);

        // 替换顶点着色器
        shader.vertexShader = shader.vertexShader.replace(
            '#define PHONG',
            HeightColor
        ).replace(
            'vViewPosition = - mvPosition.xyz;',
            [
                'vViewPosition = - mvPosition.xyz;',
                judgmentClamp,
            ].join('\n')
        );

        shader.fragmentShader = shader.fragmentShader.replace(
            '#define PHONG',
            HeightColor
        ).replace(
            'vec4 diffuseColor = vec4( diffuse, opacity );',
            'vec4 diffuseColor = vec4( diffuse * HeightColor, opacity );'
        );

        // console.log(shader.vertexShader);
        // console.log(shader.fragmentShader);

    };

    return landMaterial;

}

// 初始化陆地对象函数
function initLand() {
    landGroup = new THREE.Group();
    landGroup.name = '地质组';

    TOOLACTION = true;

    return landGroup;
}

// worker监听完成计算的回调
function workerOnMessage(data) {

    switch (data.cmd) {
        // 土地
        case 'Land':
            currArea = data.params.currArea;
            console.log(data.params);
            if (landGeometry) {
                updateLandGeometry(data.params.vertices, true);
            } else {
                loadLand(data.params.vertices);
            };
            loadLandSucceed = true;
            break;

        // 疏浚工作
        case 'Dredging':
            updateLandGeometry(data.params);
            break;

        default:
            break;
    };
}

// 请求土地数据
function requestLandData(params) {
    // console.log(params);

    requestLand(params).then(function (res) {
        // console.log('请求土地的结果：',res);
        worker.postMessage({
            cmd: 'Land',
            params: params.method === "GetLandData" ? res.data : res.data.waterDepth,
        });
    }).catch(err => {
        console.log(err)
    })
}

// 顶点创建
function loadLand(vertices) {

    landGeometry = new THREE.BufferGeometry();
    landGeometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
    // landGeometry.attributes.position.usage = THREE.StaticDrawUsage;
    landGeometry.computeVertexNormals(); // 计算法线
    // console.log(landGeometry);

    let landMesh = new THREE.Mesh(landGeometry, landMaterialFunc());
    landMesh.name = '河床表面';
    landGroup.add(landMesh);
}

function updateLandGeometry(vertices, remove) {

    if (remove) {
        // console.log(landGeometry);
        
        // console.log(landGeometry.attributes.position);
        landGeometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
        
        // landGeometry.attributes.remove(landGeometry.attributes.position);
        // landGeometry.attributes.remove(landGeometry.attributes.normal);

        // landGeometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
    } else {
        // landGeometry.attributes.position.usage = THREE.DynamicDrawUsage;
        landGeometry.attributes.position.copyArray(vertices);
        landGeometry.attributes.position.needsUpdate = true;
        // landGeometry.attributes.position.usage = THREE.StaticDrawUsage;
    }

    landGeometry.computeVertexNormals(); // 计算法线
    if(remove) console.log(landGeometry);
}

/**
 * 设置GPS 
 * 没有地质的时候，请求地质信息 
 * 有地质信息的时候，去判断是否超出边界，如果超出了边界，则要进行更新地质详细数据信息请求
 * @param {*} params 
 */
function setGPS({ x, y }) {
    // x = 30;
    // y = 300;

    if (!TOOLACTION) return;

    if (loadLandSucceed) {
        if (!currArea) return;
        const [minx, miny, maxx, maxy] = currArea;
        if (x < minx || y < miny || x > maxx || y > maxy) {
            console.log('进入', x, y);
            requestLandData({
                method: 'GetLandData',
                water_depth_file_name: waterDepthList,
                gpsX: x, gpsY: y
            })
            currArea = null; // 避免重复进入判断请求
        }
    } else {
        if (!initReuquestLand) requestLandData({
            method: 'landinit',
            start_time: Math.floor(new Date() / 1000),
            water_depth_file_name: waterDepthList,
            gpsX: x, gpsY: y
        });
        initReuquestLand = true;
    }
}

/**
 *  疏浚过程
 * @param {*} rake1 左耙数据
 * @param {*} rake2 右耙数据
 */
function dredgingByLand(rake1, rake2) {

    if (!TOOLACTION) return;

    if (loadLandSucceed) {
        if (rake1.raking) {
            worker.postMessage({
                cmd: 'Dredging',
                params: {
                    rake: rake1,
                },
            });
        }

        if (rake2.raking) {
            worker.postMessage({
                cmd: 'Dredging',
                params: {
                    rake: rake2,
                },
            });
        }
    }

}

let waterDepthList = '[7ab8b2c4-4bf0-4352-a2ef-52691677b0e7,08e4fedc-857d-4426-b0c5-6490c8619baa,52d8597d-022e-4a51-afce-226d63c0ac83,97813129-0dc2-4d05-bb11-8b6dbfa712c7,af2c5589-43a0-44c5-9cb2-171ba7a7cd7b,fd357f40-f560-4bb3-b0e3-1f8b64463a50]';

export {
    initLand, // 初始化陆地组件函数 供外部调用初始化
    setGPS,// 设置GPS参数 
    dredgingByLand, // 疏浚操作

    landMaterialFunc, // 陆地材质

    workerOnMessage, // 请求完整陆地
};

